//
//  DDQIAPHelper.m
//  AppIAPTest
//
//  Created by 我叫咚咚枪 on 2017/9/4.
//  Copyright © 2017年 DDQ. All rights reserved.
//

#import "DDQIAPHelper.h"

#import <StoreKit/StoreKit.h>
#import <AFNetworking/AFNetworking.h>

@interface DDQIAPHelper ()<SKPaymentTransactionObserver, SKProductsRequestDelegate>

@property (nonatomic, copy) DDQIAPHeplerCompletion completion;//用来记录请求的完成情况
@property (nonatomic, copy) DDQIAPHeplerRequestStatus status;//用来记录UI的更新状态
@end

@implementation DDQIAPHelper

+ (instancetype)helper {
    
    return [[self alloc] init];
}

- (id)copyWithZone:(NSZone *)zone {
    
    return [[DDQIAPHelper allocWithZone:zone] init];
}

- (instancetype)init {
    
    self = [super init];
    if (!self) return nil;
    
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    return self;
}

- (void)dealloc {
    
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

+ (BOOL)iap_allow {
    
    return [SKPaymentQueue canMakePayments];
}

- (void)iap_sendRequestWithProductIdentifier:(NSString *)identifier asyncCompletion:(DDQIAPHeplerCompletion)completion asyncStatus:(DDQIAPHeplerRequestStatus)asyncStatus {
    
    NSSet *set = [NSSet setWithObject:identifier];
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
    request.delegate = self;
    [request start];
    
    if (completion) self.completion = completion;
    if (asyncStatus) self.status = asyncStatus;
    if (self.status) self.status(DDQIAPHeplerStatusStart);
}

- (void)iap_sendRequestWithProductIdentifier:(NSString *)identifier syncCompletion:(DDQIAPHeplerCompletion)completion syncStatus:(DDQIAPHeplerRequestStatus)syncStatus {
    
    [self iap_sendRequestWithProductIdentifier:identifier asyncCompletion:^(NSError * _Nullable error) {
        
        if ([NSThread isMainThread]) {
            if (completion) completion(error);
        } else {
            
            dispatch_async(dispatch_get_main_queue(), ^{
                if (completion) completion(error);
            });
        }
    } asyncStatus:^(DDQIAPHeplerStatus asyncStatus) {
        
        if ([NSThread isMainThread]) {
            if (asyncStatus) syncStatus(asyncStatus);
        } else {
            
            dispatch_async(dispatch_get_main_queue(), ^{
                if (asyncStatus) syncStatus(asyncStatus);
            });
        }
    }];
}

#pragma mark - Queue Delegate
/**
 处理交易状态
 */
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {
    
    for (SKPaymentTransaction *transaction in transactions) {
        
        if (transaction.transactionState == SKPaymentTransactionStatePurchased) {//购买成功
            
            [queue finishTransaction:transaction];
            [self iap_verifyReceiptFromiTunesStore];
        } else if (transaction.transactionState == SKPaymentTransactionStateFailed) {//购买失败
            
            [queue finishTransaction:transaction];
            
            NSString *domain = @"";
            switch (transaction.error.code) {
                    
                case SKErrorPaymentCancelled:
                    domain = @"您取消了支付";
                    break;
                    
                case SKErrorPaymentInvalid:
                    domain = @"交易无效";
                    break;
                    
                case SKErrorPaymentNotAllowed:
                    domain = @"交易失败";
                    break;
                    
                case SKErrorStoreProductNotAvailable:
                    domain = @"未能找到对应商品";
                    break;
                    
                case SKErrorUnknown:
                    domain = transaction.error.userInfo[NSLocalizedDescriptionKey];
                    break;
                    
                default:
                    break;
            }
            
            NSError *requestError = [NSError errorWithDomain:domain code:DDQIAPHeplerErrorTransactionFailure userInfo:nil];
            if (self.completion) self.completion(requestError);
            if (self.status) self.status(DDQIAPHeplerStatusEnd);
        } else if (transaction.transactionState == SKPaymentTransactionStatePurchasing) {//正在购买
            
            if (self.status) self.status(DDQIAPHeplerStatusStart);
        } else if (transaction.transactionState == SKPaymentTransactionStateRestored) {//恢复交易
            
            NSLog(@"%@", transaction.originalTransaction);
        } else {//交易延迟
            
            if (self.status) self.status(DDQIAPHeplerStatusStart);
        }
    }
}

/**
 向iTunesStore验证收据
 */
- (void)iap_verifyReceiptFromiTunesStore {
    
    NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];
    
    //收据数据不为空
    if (receiptData.length == 0 || !receiptData) return;
    NSString *base64EncodeStr = [receiptData base64EncodedStringWithOptions:0];
    
    NSString *url = @"https://buy.itunes.apple.com/verifyReceipt";
    NSDictionary *param = @{@"receipt-data":base64EncodeStr};
    [self iap_checkIAPEnvironmentWithUrl:url param:param];
}

/**
 根据接口返回值判断当前IAP环境

 @param url 请求的接口地址
 @param param 请求的参数
 */
- (void)iap_checkIAPEnvironmentWithUrl:(NSString *)url param:(NSDictionary *)param {

    NSLog(@"%@", url);
    
    //Request Config
    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
    [urlRequest setHTTPMethod:@"POST"];
    NSData *data = [NSJSONSerialization dataWithJSONObject:param options:NSJSONWritingPrettyPrinted error:nil];
    [urlRequest setHTTPBody:data];
    
    //Session Config
    if (self.status) self.status(DDQIAPHeplerStatusStart);//开始loading
    NSURLSession *session = [NSURLSession sharedSession];
    __weak typeof(self) weakSelf = self;
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            NSError *error = [NSError errorWithDomain:@"链接iTunesStore服务器出错" code:DDQIAPHelperErrorRequestITunesStoreFailure userInfo:nil];
            if (weakSelf.completion) weakSelf.completion(error);
            return;
        }
        NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        int status = [[jsonDic valueForKey:@"status"] intValue];
        if (status == 0) {
            
            if (weakSelf.completion) weakSelf.completion(nil);
        } else {
            
            if (status == 21007) {//数据是测试环境的却发送到了生产环境当中
                
                //PS:这种情况会出现在App的审核中，但是我并没有发现更好的方法先这么弄了。
                [weakSelf iap_checkIAPEnvironmentWithUrl:@"https://sandbox.itunes.apple.com/verifyReceipt" param:param];
            } else if (status == 21008) {//数据是生产环境的却发送到了测试环境当中
                
                [weakSelf iap_checkIAPEnvironmentWithUrl:@"https://buy.itunes.apple.com/verifyReceipt" param:param];
            } else {
            
                NSError *error = [NSError errorWithDomain:@"iTunseStore验证出错了" code:DDQIAPHelperErrorITunesStoreVerifiedFailure userInfo:nil];
                if (self.completion) self.completion(error);
            }
        }
        if (weakSelf.status) weakSelf.status(DDQIAPHeplerStatusEnd);
    }];
    [dataTask resume];
}
#pragma makr - Request Delegate
/**
 收到iTunesStore的商品响应
 */
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
    
    if (response.products.count == 0) {
        
        NSError *error = [NSError errorWithDomain:@"未能获取到商品信息" code:DDQIAPHeplerErrorNotProductInfo userInfo:nil];
        if (self.completion) self.completion(error);
        return;
    }
    
    for (SKProduct *product in response.products) {
        
        SKPayment *payment = [SKPayment paymentWithProduct:product];
        [[SKPaymentQueue defaultQueue] addPayment:payment];
    }
}

/**
 iTunesStore请求结束
 */
- (void)requestDidFinish:(SKRequest *)request {
    
    if (self.status) self.status(DDQIAPHeplerStatusEnd);
}

/**
 iTunesStore访问失败
 */
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
    
    [request cancel];
    if (error) {
        
        NSError *requestError = [NSError errorWithDomain:@"发起支付请求失败" code:DDQIAPHeplerErrorRequestFailure userInfo:nil];
        if (self.completion) self.completion(requestError);
    }
    if (request.delegate) request.delegate = nil;
    if (self.status) self.status(DDQIAPHeplerStatusEnd);
}

@end
